home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2000 #5 / Amiga Plus CD - 2000 - No. 5.iso / Tools / Dev / fpc / inc / math.inc < prev    next >
Text File  |  1998-10-28  |  34KB  |  943 lines

  1. {
  2.     $Id: math.inc,v 1.1.1.1 1998/03/25 11:18:44 root Exp $
  3.     This file is part of the Free Pascal run time library.
  4.     Copyright (c) 1993,97 by several people
  5.     member of the Free Pascal development team.
  6.  
  7.     See the file COPYING.FPC, included in this distribution,
  8.     for details about the copyright.
  9.  
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13.  
  14.  **********************************************************************}
  15. {*************************************************************************}
  16. {  math.inc                                                               }
  17. {*************************************************************************}
  18. {       Copyright Abandoned, 1987, Fred Fish                              }
  19. {                                                                         }
  20. {       This previously copyrighted work has been placed into the         }
  21. {       public domain by the author (Fred Fish) and may be freely used    }
  22. {       for any purpose, private or commercial.  I would appreciate       }
  23. {       it, as a courtesy, if this notice is left in all copies and       }
  24. {       derivative works.  Thank you, and enjoy...                        }
  25. {                                                                         }
  26. {       The author makes no warranty of any kind with respect to this     }
  27. {       product and explicitly disclaims any implied warranties of        }
  28. {       merchantability or fitness for any particular purpose.            }
  29. {-------------------------------------------------------------------------}
  30. {       Copyright (c) 1992 Odent Jean Philippe                            }
  31. {                                                                         }
  32. {       The source can be modified as long as my name appears and some    }
  33. {       notes explaining the modifications done are included in the file. }
  34. {-------------------------------------------------------------------------}
  35. {       Copyright (c) 1997 Carl Eric Codere                               }
  36. {                                                                         }
  37. {*************************************************************************}
  38. {  This is the Motorola 680x0 specific port of the math include.          }
  39. {*************************************************************************}
  40. {                                                                         }
  41. {  o all reals are mapped to the single type under the motorola version   }
  42. {                                                                         }
  43. {   What is left to do:                                                   }
  44. {    o add support for sqrt with fixed.                                   }
  45.  
  46. type
  47.     TabCoef = array[0..6] of Real;
  48.  
  49.  
  50. const
  51.       PIO2   =  1.57079632679489661923;       {  pi/2        }
  52.       PIO4   =  7.85398163397448309616E-1;    {  pi/4        }
  53.       SQRT2  =  1.41421356237309504880;       {  sqrt(2)     }
  54.       SQRTH  =  7.07106781186547524401E-1;    {  sqrt(2)/2   }
  55.       LOG2E  =  1.4426950408889634073599;     {  1/log(2)    }
  56.       SQ2OPI =  7.9788456080286535587989E-1;  {  sqrt( 2/pi )}
  57.       LOGE2  =  6.93147180559945309417E-1;    {  log(2)      }
  58.       LOGSQ2 =  3.46573590279972654709E-1;    {  log(2)/2    }
  59.       THPIO4 =  2.35619449019234492885;       {  3*pi/4      }
  60.       TWOOPI =  6.36619772367581343075535E-1; {  2/pi        }
  61.       lossth =  1.073741824e9;
  62.       MAXLOG =  8.8029691931113054295988E1;    { log(2**127)  }
  63.       MINLOG = -8.872283911167299960540E1;     { log(2**-128) }
  64.  
  65.       DP1 =   7.85398125648498535156E-1;
  66.       DP2 =   3.77489470793079817668E-8;
  67.       DP3 =   2.69515142907905952645E-15;
  68.  
  69. const sincof : TabCoef = (
  70.                 1.58962301576546568060E-10,
  71.                -2.50507477628578072866E-8,
  72.                 2.75573136213857245213E-6,
  73.                -1.98412698295895385996E-4,
  74.                 8.33333333332211858878E-3,
  75.                -1.66666666666666307295E-1, 0);
  76.       coscof : TabCoef = (
  77.                -1.13585365213876817300E-11,
  78.                 2.08757008419747316778E-9,
  79.                -2.75573141792967388112E-7,
  80.                 2.48015872888517045348E-5,
  81.                -1.38888888888730564116E-3,
  82.                 4.16666666666665929218E-2, 0);
  83.  
  84.  
  85.  
  86.  
  87.     function int(d : real) : real;
  88.       begin
  89.         { this will be correct since real = single in the case of }
  90.         { the motorola version of the compiler...                 }
  91.         int:=real(trunc(d));
  92.       end;
  93.  
  94.     function trunc(d : real) : longint;
  95.     var
  96.      l: longint;
  97.     Begin
  98.      asm
  99.         move.l   d,d0           { get number                        }
  100.         move.l   d2,-(sp)       { save register                     }
  101.         move.l   d0,d1
  102.         swap     d1             { extract exp                       }
  103.         move.w   d1,d2          { extract sign                      }
  104.         bclr     #15,d1         { kill sign bit                     }
  105.         lsr.w    #7,d1
  106.  
  107.         and.l    #$7fffff,d0    { remove exponent from mantissa     }
  108.         bset     #23,d0         { restore implied leading "1"       }
  109.  
  110.         cmp.w    #BIAS4,d1      { check exponent                    }
  111.         blt      @zero           { strictly factional, no integer part ?   }
  112.         cmp.w    #BIAS4+32,d1   { is it too big to fit in a 32-bit integer ? }
  113.         bgt      @toobig
  114.  
  115.         sub.w    #BIAS4+24,d1   { adjust exponent                   }
  116.         bgt      @trunclab2     { shift up                          }
  117.         beq      @trunclab7     { no shift (never too big)          }
  118.  
  119.         neg.w    d1
  120.         lsr.l    d1,d0          { shift down to align radix point;  }
  121.               { extra bits fall off the end (no rounding) }
  122.         bra      @trunclab7      { never too big                     }
  123.     @trunclab2:
  124.         lsl.l   d1,d0           { shift up to align radix point     }
  125.     @trunclab3:
  126.         cmp.l   #$80000000,d0   { -2147483648 is a nasty evil special case }
  127.         bne      @trunclab6
  128.         tst.w    d2             { this had better be -2^31 and not 2^31    }
  129.         bpl      @toobig
  130.         bra      @trunclab8
  131.     @trunclab6:
  132.         tst.l   d0              { sign bit set ? (i.e. too big)     }
  133.         bmi     @toobig
  134.     @trunclab7:
  135.         tst.w   d2              { is it negative ?                  }
  136.         bpl     @trunclab8
  137.         neg.l   d0              { negate                            }
  138.         bra     @trunclab8
  139.     @zero:
  140.         clr.l   d0              { make the whole thing zero         }
  141.         bra     @trunclab8
  142.     @toobig:
  143.         moveq   #-1,d0          { ugh. Should cause a trap here.    }
  144.         bclr    #31,d0          { make it #0x7fffffff               }
  145.     @trunclab8:
  146.         move.l  (sp)+,d2
  147.         move.l  d0,l
  148.      end;
  149.      if l = $7fffffff then
  150.       RunError(207)
  151.      else
  152.        trunc := l
  153.     end;
  154.  
  155.  
  156.  
  157.  
  158.  
  159.     function abs(d : Real) : Real;
  160.     begin
  161.        if( d < 0.0 ) then
  162.          abs := -d
  163.       else
  164.          abs := d ;
  165.     end;
  166.  
  167.  
  168.     function frexp(x:Real; var e:Integer ):Real;
  169.     {*  frexp() extracts the exponent from x.  It returns an integer     *}
  170.     {*  power of two to expnt and the significand between 0.5 and 1      *}
  171.     {*  to y.  Thus  x = y * 2**expn.                                    *}
  172.     begin
  173.       e :=0;
  174.       if (abs(x)<0.5) then
  175.        While (abs(x)<0.5) do
  176.        begin
  177.          x := x*2;
  178.          Dec(e);
  179.        end
  180.       else
  181.        While (abs(x)>1) do
  182.        begin
  183.          x := x/2;
  184.          Inc(e);
  185.        end;
  186.       frexp := x;
  187.     end;
  188.  
  189.  
  190.     function ldexp( x: Real; N: Integer):Real;
  191.     {* ldexp() multiplies x by 2**n.                                    *}
  192.     var r : Real;
  193.     begin
  194.       R := 1;
  195.       if N>0 then
  196.          while N>0 do
  197.          begin
  198.             R:=R*2;
  199.             Dec(N);
  200.          end
  201.       else
  202.         while N<0 do
  203.         begin
  204.            R:=R/2;
  205.            Inc(N);
  206.         end;
  207.       ldexp := x * R;
  208.     end;
  209.  
  210.  
  211.     function polevl(var x:Real; var Coef:TabCoef; N:Integer):Real;
  212.     {*****************************************************************}
  213.     { Evaluate polynomial                                             }
  214.     {*****************************************************************}
  215.     {                                                                 }
  216.     { SYNOPSIS:                                                       }
  217.     {                                                                 }
  218.     {  int N;                                                         }
  219.     {  double x, y, coef[N+1], polevl[];                              }
  220.     {                                                                 }
  221.     {  y = polevl( x, coef, N );                                      }
  222.     {                                                                 }
  223.     {  DESCRIPTION:                                                   }
  224.     {                                                                 }
  225.     {     Evaluates polynomial of degree N:                           }
  226.     {                                                                 }
  227.     {                       2          N                              }
  228.     {   y  =  C  + C x + C x  +...+ C x                               }
  229.     {          0    1     2          N                                }
  230.     {                                                                 }
  231.     {   Coefficients are stored in reverse order:                     }
  232.     {                                                                 }
  233.     {   coef[0] = C  , ..., coef[N] = C  .                            }
  234.     {              N                   0                              }
  235.     {                                                                 }
  236.     {   The function p1evl() assumes that coef[N] = 1.0 and is        }
  237.     {   omitted from the array.  Its calling arguments are            }
  238.     {   otherwise the same as polevl().                               }
  239.     {                                                                 }
  240.     {  SPEED:                                                         }
  241.     {                                                                 }
  242.     {   In the interest of speed, there are no checks for out         }
  243.     {   of bounds arithmetic.  This routine is used by most of        }
  244.     {   the functions in the library.  Depending on available         }
  245.     {   equipment features, the user may wish to rewrite the          }
  246.     {   program in microcode or assembly language.                    }
  247.     {*****************************************************************}
  248.     var ans : Real;
  249.         i   : Integer;
  250.  
  251.     begin
  252.       ans := Coef[0];
  253.       for i:=1 to N do
  254.         ans := ans * x + Coef[i];
  255.       polevl:=ans;
  256.     end;
  257.  
  258.  
  259.     function p1evl(var x:Real; var Coef:TabCoef; N:Integer):Real;
  260.     {                                                           }
  261.     { Evaluate polynomial when coefficient of x  is 1.0.        }
  262.     { Otherwise same as polevl.                                 }
  263.     {                                                           }
  264.     var
  265.         ans : Real;
  266.         i   : Integer;
  267.     begin
  268.       ans := x + Coef[0];
  269.       for i:=1 to N-1 do
  270.         ans := ans * x + Coef[i];
  271.       p1evl := ans;
  272.     end;
  273.  
  274.  
  275.  
  276.  
  277.  
  278.     function sqr(d : Real) : Real;
  279.     begin
  280.       sqr := d*d;
  281.     end;
  282.  
  283.  
  284.     function pi : Real;
  285.     begin
  286.       pi := 3.1415926535897932385;
  287.     end;
  288.  
  289.  
  290.     function sqrt(d:Real):Real;
  291.     {*****************************************************************}
  292.     { Square root                                                     }
  293.     {*****************************************************************}
  294.     {                                                                 }
  295.     { SYNOPSIS:                                                       }
  296.     {                                                                 }
  297.     { double x, y, sqrt();                                            }
  298.     {                                                                 }
  299.     { y = sqrt( x );                                                  }
  300.     {                                                                 }
  301.     { DESCRIPTION:                                                    }
  302.     {                                                                 }
  303.     { Returns the square root of x.                                   }
  304.     {                                                                 }
  305.     { Range reduction involves isolating the power of two of the      }
  306.     { argument and using a polynomial approximation to obtain         }
  307.     { a rough value for the square root.  Then Heron's iteration      }
  308.     { is used three times to converge to an accurate value.           }
  309.     {*****************************************************************}
  310.     var e   : Integer;
  311.         w,z : Real;
  312.     begin
  313.        if( d <= 0.0 ) then
  314.        begin
  315.            if( d < 0.0 ) then
  316.                RunError(207);
  317.            sqrt := 0.0;
  318.        end
  319.      else
  320.        begin
  321.           w := d;
  322.           { separate exponent and significand }
  323.            z := frexp( d, e );
  324.  
  325.           {  approximate square root of number between 0.5 and 1  }
  326.           {  relative error of approximation = 7.47e-3            }
  327.           d := 4.173075996388649989089E-1 + 5.9016206709064458299663E-1 * z;
  328.  
  329.           { adjust for odd powers of 2 }
  330.           if odd(e) then
  331.              d := d*SQRT2;
  332.  
  333.           { re-insert exponent }
  334.           d := ldexp( d, (e div 2) );
  335.  
  336.           { Newton iterations: }
  337.           d := 0.5*(d + w/d);
  338.           d := 0.5*(d + w/d);
  339.           d := 0.5*(d + w/d);
  340.           d := 0.5*(d + w/d);
  341.           d := 0.5*(d + w/d);
  342.           d := 0.5*(d + w/d);
  343.           sqrt := d;
  344.        end;
  345.     end;
  346.  
  347.  
  348.  
  349.  
  350.     function Exp(d:Real):Real;
  351.     {*****************************************************************}
  352.     { Exponential Function                                            }
  353.     {*****************************************************************}
  354.     {                                                                 }
  355.     { SYNOPSIS:                                                       }
  356.     {                                                                 }
  357.     { double x, y, exp();                                             }
  358.     {                                                                 }
  359.     { y = exp( x );                                                   }
  360.     {                                                                 }
  361.     { DESCRIPTION:                                                    }
  362.     {                                                                 }
  363.     { Returns e (2.71828...) raised to the x power.                   }
  364.     {                                                                 }
  365.     { Range reduction is accomplished by separating the argument      }
  366.     { into an integer k and fraction f such that                      }
  367.     {                                                                 }
  368.     {     x    k  f                                                   }
  369.     {    e  = 2  e.                                                   }
  370.     {                                                                 }
  371.     { A Pade' form of degree 2/3 is used to approximate exp(f)- 1     }
  372.     { in the basic range [-0.5 ln 2, 0.5 ln 2].                       }
  373.     {*****************************************************************}
  374.     const  P : TabCoef = (
  375.            1.26183092834458542160E-4,
  376.            3.02996887658430129200E-2,
  377.            1.00000000000000000000E0, 0, 0, 0, 0);
  378.            Q : TabCoef = (
  379.            3.00227947279887615146E-6,
  380.            2.52453653553222894311E-3,
  381.            2.27266044198352679519E-1,
  382.            2.00000000000000000005E0, 0 ,0 ,0);
  383.  
  384.            C1 = 6.9335937500000000000E-1;
  385.             C2 = 2.1219444005469058277E-4;
  386.     var n : Integer;
  387.         px, qx, xx : Real;
  388.     begin
  389.       if( d > MAXLOG) then
  390.           RunError(205)
  391.       else
  392.       if( d < MINLOG ) then
  393.       begin
  394.         Runerror(205);
  395.       end
  396.       else
  397.       begin
  398.  
  399.      { Express e**x = e**g 2**n }
  400.      {   = e**g e**( n loge(2) ) }
  401.      {   = e**( g + n loge(2) )  }
  402.  
  403.         px := d * LOG2E;
  404.         qx := Trunc( px + 0.5 ); { Trunc() truncates toward -infinity. }
  405.         n  := Trunc(qx);
  406.         d  := d - qx * C1;
  407.         d  := d + qx * C2;
  408.  
  409.       { rational approximation for exponential  }
  410.       { of the fractional part: }
  411.       { e**x - 1  =  2x P(x**2)/( Q(x**2) - P(x**2) )  }
  412.         xx := d * d;
  413.         px := d * polevl( xx, P, 2 );
  414.         d  :=  px/( polevl( xx, Q, 3 ) - px );
  415.         d  := ldexp( d, 1 );
  416.         d  :=  d + 1.0;
  417.         d  := ldexp( d, n );
  418.         Exp := d;
  419.       end;
  420.     end;
  421.  
  422.  
  423.     function Round(d: Real): longint;
  424.      var
  425.       fr: Real;
  426.       tr: Real;
  427.     Begin
  428.        fr := Frac(d);
  429.        tr := Trunc(d);
  430.        if fr > 0.5 then
  431.           Round:=Trunc(d)+1
  432.        else
  433.        if fr < 0.5 then
  434.           Round:=Trunc(d)
  435.        else { fr = 0.5 }
  436.           { check sign to decide ... }
  437.           { as in Turbo Pascal...    }
  438.           if d >= 0.0 then
  439.             Round := Trunc(d)+1
  440.           else
  441.             Round := Trunc(d);
  442.     end;
  443.  
  444.  
  445.     function Ln(d:Real):Real;
  446.     {*****************************************************************}
  447.     { Natural Logarithm                                               }
  448.     {*****************************************************************}
  449.     {                                                                 }
  450.     { SYNOPSIS:                                                       }
  451.     {                                                                 }
  452.     { double x, y, log();                                             }
  453.     {                                                                 }
  454.     { y = ln( x );                                                    }
  455.     {                                                                 }
  456.     { DESCRIPTION:                                                    }
  457.     {                                                                 }
  458.     { Returns the base e (2.718...) logarithm of x.                   }
  459.     {                                                                 }
  460.     { The argument is separated into its exponent and fractional      }
  461.     { parts.  If the exponent is between -1 and +1, the logarithm     }
  462.     { of the fraction is approximated by                              }
  463.     {                                                                 }
  464.     {     log(1+x) = x - 0.5 x**2 + x**3 P(x)/Q(x).                   }
  465.     {                                                                 }
  466.     { Otherwise, setting  z = 2(x-1)/x+1),                            }
  467.     {                                                                 }
  468.     {     log(x) = z + z**3 P(z)/Q(z).                                }
  469.     {                                                                 }
  470.     {*****************************************************************}
  471.     const  P : TabCoef = (
  472.      {  Coefficients for log(1+x) = x - x**2/2 + x**3 P(x)/Q(x)
  473.          1/sqrt(2) <= x < sqrt(2) }
  474.  
  475.            4.58482948458143443514E-5,
  476.            4.98531067254050724270E-1,
  477.            6.56312093769992875930E0,
  478.            2.97877425097986925891E1,
  479.            6.06127134467767258030E1,
  480.            5.67349287391754285487E1,
  481.            1.98892446572874072159E1);
  482.        Q : TabCoef = (
  483.            1.50314182634250003249E1,
  484.            8.27410449222435217021E1,
  485.            2.20664384982121929218E2,
  486.            3.07254189979530058263E2,
  487.            2.14955586696422947765E2,
  488.            5.96677339718622216300E1, 0);
  489.  
  490.      { Coefficients for log(x) = z + z**3 P(z)/Q(z),
  491.         where z = 2(x-1)/(x+1)
  492.         1/sqrt(2) <= x < sqrt(2)  }
  493.  
  494.        R : TabCoef = (
  495.            -7.89580278884799154124E-1,
  496.             1.63866645699558079767E1,
  497.            -6.41409952958715622951E1, 0, 0, 0, 0);
  498.        S : TabCoef = (
  499.            -3.56722798256324312549E1,
  500.             3.12093766372244180303E2,
  501.            -7.69691943550460008604E2, 0, 0, 0, 0);
  502.  
  503.     var e : Integer;
  504.        z, y : Real;
  505.  
  506.     Label Ldone;
  507.     begin
  508.        if( d <= 0.0 ) then
  509.           RunError(207);
  510.        d := frexp( d, e );
  511.  
  512.     { logarithm using log(x) = z + z**3 P(z)/Q(z),
  513.       where z = 2(x-1)/x+1) }
  514.  
  515.        if( (e > 2) or (e < -2) ) then
  516.        begin
  517.          if( d < SQRTH ) then
  518.          begin
  519.            {  2( 2x-1 )/( 2x+1 ) }
  520.           Dec(e, 1);
  521.           z := d - 0.5;
  522.           y := 0.5 * z + 0.5;
  523.          end
  524.          else
  525.          begin
  526.          {   2 (x-1)/(x+1)   }
  527.            z := d - 0.5;
  528.          z := z - 0.5;
  529.          y := 0.5 * d  + 0.5;
  530.          end;
  531.          d := z / y;
  532.          { /* rational form */ }
  533.          z := d*d;
  534.          z := d + d * ( z * polevl( z, R, 2 ) / p1evl( z, S, 3 ) );
  535.          goto ldone;
  536.        end;
  537.  
  538.     { logarithm using log(1+x) = x - .5x**2 + x**3 P(x)/Q(x) }
  539.  
  540.        if( d < SQRTH ) then
  541.        begin
  542.          Dec(e, 1);
  543.          d := ldexp( d, 1 ) - 1.0; {  2x - 1  }
  544.        end
  545.        else
  546.          d := d - 1.0;
  547.  
  548.        { rational form  }
  549.        z := d*d;
  550.        y := d * ( z * polevl( d, P, 6 ) / p1evl( d, Q, 6 ) );
  551.        y := y - ldexp( z, -1 );   {  y - 0.5 * z  }
  552.        z := d + y;
  553.  
  554.     ldone:
  555.        { recombine with exponent term }
  556.        if( e <> 0 ) then
  557.        begin
  558.          y := e;
  559.          z := z - y * 2.121944400546905827679e-4;
  560.          z := z + y * 0.693359375;
  561.        end;
  562.  
  563.        Ln:= z;
  564.     end;
  565.  
  566.  
  567.  
  568.     function Sin(d:Real):Real;
  569.     {*****************************************************************}
  570.     { Circular Sine                                                   }
  571.     {*****************************************************************}
  572.     {                                                                 }
  573.     { SYNOPSIS:                                                       }
  574.     {                                                                 }
  575.     { double x, y, sin();                                             }
  576.     {                                                                 }
  577.     { y = sin( x );                                                   }
  578.     {                                                                 }
  579.     { DESCRIPTION:                                                    }
  580.     {                                                                 }
  581.     { Range reduction is into intervals of pi/4.  The reduction       }
  582.     { error is nearly eliminated by contriving an extended            }
  583.     { precision modular arithmetic.                                   }
  584.     {                                                                 }
  585.     { Two polynomial approximating functions are employed.            }
  586.     { Between 0 and pi/4 the sine is approximated by                  }
  587.     {      x  +  x**3 P(x**2).                                        }
  588.     { Between pi/4 and pi/2 the cosine is represented as              }
  589.     {      1  -  x**2 Q(x**2).                                        }
  590.     {*****************************************************************}
  591.     var  y, z, zz : Real;
  592.          j, sign : Integer;
  593.  
  594.     begin
  595.       { make argument positive but save the sign }
  596.       sign := 1;
  597.       if( d < 0 ) then
  598.       begin
  599.          d := -d;
  600.          sign := -1;
  601.       end;
  602.  
  603.       { above this value, approximate towards 0 }
  604.       if( d > lossth ) then
  605.       begin
  606.         sin := 0.0;
  607.         exit;
  608.       end;
  609.  
  610.       y := Trunc( d/PIO4 ); { integer part of x/PIO4 }
  611.  
  612.       { strip high bits of integer part to prevent integer overflow }
  613.       z := ldexp( y, -4 );
  614.       z := Trunc(z);           { integer part of y/8 }
  615.       z := y - ldexp( z, 4 );  { y - 16 * (y/16) }
  616.  
  617.       j := Trunc(z); { convert to integer for tests on the phase angle }
  618.       { map zeros to origin }
  619.       if odd( j ) then
  620.       begin
  621.          inc(j);
  622.          y := y + 1.0;
  623.       end;
  624.       j := j and 7; { octant modulo 360 degrees }
  625.       { reflect in x axis }
  626.       if( j > 3) then
  627.       begin
  628.         sign := -sign;
  629.         dec(j, 4);
  630.       end;
  631.  
  632.       { Extended precision modular arithmetic }
  633.       z := ((d - y * DP1) - y * DP2) - y * DP3;
  634.  
  635.       zz := z * z;
  636.  
  637.       if( (j=1) or (j=2) ) then
  638.         y := 1.0 - ldexp(zz,-1) + zz * zz * polevl( zz, coscof, 5 )
  639.       else
  640.       { y = z  +  z * (zz * polevl( zz, sincof, 5 )); }
  641.         y := z  +  z * z * z * polevl( zz, sincof, 5 );
  642.  
  643.       if(sign < 0) then
  644.       y := -y;
  645.       sin := y;
  646.     end;
  647.  
  648.  
  649.  
  650.  
  651.     function Cos(d:Real):Real;
  652.     {*****************************************************************}
  653.     { Circular cosine                                                 }
  654.     {*****************************************************************}
  655.     {                                                                 }
  656.     { Circular cosine                                                 }
  657.     {                                                                 }
  658.     { SYNOPSIS:                                                       }
  659.     {                                                                 }
  660.     { double x, y, cos();                                             }
  661.     {                                                                 }
  662.     { y = cos( x );                                                   }
  663.     {                                                                 }
  664.     { DESCRIPTION:                                                    }
  665.     {                                                                 }
  666.     { Range reduction is into intervals of pi/4.  The reduction       }
  667.     { error is nearly eliminated by contriving an extended            }
  668.     { precision modular arithmetic.                                   }
  669.     {                                                                 }
  670.     { Two polynomial approximating functions are employed.            }
  671.     { Between 0 and pi/4 the cosine is approximated by                }
  672.     {      1  -  x**2 Q(x**2).                                        }
  673.     { Between pi/4 and pi/2 the sine is represented as                }
  674.     {      x  +  x**3 P(x**2).                                        }
  675.     {*****************************************************************}
  676.     var  y, z, zz : Real;
  677.          j, sign : Integer;
  678.          i : LongInt;
  679.     begin
  680.     { make argument positive }
  681.       sign := 1;
  682.       if( d < 0 ) then
  683.         d := -d;
  684.  
  685.       { above this value, round towards zero }
  686.       if( d > lossth ) then
  687.       begin
  688.         cos := 0.0;
  689.         exit;
  690.       end;
  691.  
  692.       y := Trunc( d/PIO4 );
  693.       z := ldexp( y, -4 );
  694.       z := Trunc(z);  { integer part of y/8 }
  695.       z := y - ldexp( z, 4 );  { y - 16 * (y/16) }
  696.  
  697.       { integer and fractional part modulo one octant }
  698.       i := Trunc(z);
  699.       if odd( i ) then { map zeros to origin }
  700.       begin
  701.         inc(i);
  702.         y := y + 1.0;
  703.       end;
  704.       j := i and 07;
  705.       if( j > 3) then
  706.       begin
  707.         dec(j,4);
  708.         sign := -sign;
  709.       end;
  710.       if( j > 1 ) then
  711.         sign := -sign;
  712.  
  713.       { Extended precision modular arithmetic  }
  714.       z := ((d - y * DP1) - y * DP2) - y * DP3;
  715.  
  716.       zz := z * z;
  717.  
  718.       if( (j=1) or (j=2) ) then
  719.       { y = z  +  z * (zz * polevl( zz, sincof, 5 )); }
  720.         y := z  +  z * z * z * polevl( zz, sincof, 5 )
  721.       else
  722.         y := 1.0 - ldexp(zz,-1) + zz * zz * polevl( zz, coscof, 5 );
  723.  
  724.       if(sign < 0) then
  725.         y := -y;
  726.  
  727.       cos := y ;
  728.     end;
  729.  
  730.  
  731.  
  732.     function ArcTan(d:Real):Real;
  733.     {*****************************************************************}
  734.     { Inverse circular tangent (arctangent)                           }
  735.     {*****************************************************************}
  736.     {                                                                 }
  737.     { SYNOPSIS:                                                       }
  738.     {                                                                 }
  739.     { double x, y, atan();                                            }
  740.     {                                                                 }
  741.     { y = atan( x );                                                  }
  742.     {                                                                 }
  743.     { DESCRIPTION:                                                    }
  744.     {                                                                 }
  745.     { Returns radian angle between -pi/2 and +pi/2 whose tangent      }
  746.     { is x.                                                           }
  747.     {                                                                 }
  748.     { Range reduction is from four intervals into the interval        }
  749.     { from zero to  tan( pi/8 ).  The approximant uses a rational     }
  750.     { function of degree 3/4 of the form x + x**3 P(x)/Q(x).          }
  751.     {*****************************************************************}
  752.     const P : TabCoef = (
  753.           -8.40980878064499716001E-1,
  754.           -8.83860837023772394279E0,
  755.           -2.18476213081316705724E1,
  756.           -1.48307050340438946993E1, 0, 0, 0);
  757.           Q : TabCoef = (
  758.           1.54974124675307267552E1,
  759.           6.27906555762653017263E1,
  760.           9.22381329856214406485E1,
  761.           4.44921151021319438465E1, 0, 0, 0);
  762.  
  763.     { tan( 3*pi/8 ) }
  764.     T3P8 = 2.41421356237309504880;
  765.     { tan( pi/8 )   }
  766.     TP8 = 0.41421356237309504880;
  767.  
  768.     var y,z  : Real;
  769.         Sign : Integer;
  770.  
  771.     begin
  772.       { make argument positive and save the sign }
  773.       sign := 1;
  774.       if( d < 0.0 ) then
  775.       begin
  776.        sign := -1;
  777.        d := -d;
  778.       end;
  779.  
  780.       { range reduction }
  781.       if( d > T3P8 ) then
  782.       begin
  783.         y := PIO2;
  784.         d := -( 1.0/d );
  785.       end
  786.       else if( d > TP8 ) then
  787.       begin
  788.         y := PIO4;
  789.         d := (d-1.0)/(d+1.0);
  790.       end
  791.       else
  792.        y := 0.0;
  793.  
  794.       { rational form in x**2 }
  795.  
  796.       z := d * d;
  797.       y := y + ( polevl( z, P, 3 ) / p1evl( z, Q, 4 ) ) * z * d + d;
  798.  
  799.       if( sign < 0 ) then
  800.         y := -y;
  801.       Arctan := y;
  802.     end;
  803.  
  804.     function frac(d : Real) : Real;
  805.     begin
  806.        frac := d - Int(d);
  807.     end;
  808.  
  809. {$ifdef fixed}
  810.  
  811.  
  812.     function sqrt(d : fixed) : fixed;
  813.       begin
  814.       end;
  815.  
  816.     function int(d : fixed) : fixed; assembler;
  817.     {*****************************************************************}
  818.     { Returns the integral part of d                                  }
  819.     {*****************************************************************}
  820.     asm
  821.       move.l d,d0
  822.       and.l  #$ffff0000,d0        { keep only upper bits   .. }
  823.     end;
  824.  
  825.  
  826.     function trunc(d : fixed) : longint;
  827.     {*****************************************************************}
  828.     { Returns the Truncated integral part of d                        }
  829.     {*****************************************************************}
  830.     begin
  831.       trunc:=longint(integer(d shr 16));   { keep only upper 16 bits  }
  832.     end;
  833.  
  834.     function frac(d : fixed) : fixed; assembler;
  835.     {*****************************************************************}
  836.     { Returns the Fractional part of d                                }
  837.     {*****************************************************************}
  838.     asm
  839.       move.l d,d0
  840.       and.l  #$ffff,d0           { keep only decimal parts - lower 16 bits }
  841.     end;
  842.  
  843.     function abs(d : fixed) : fixed;
  844.     {*****************************************************************}
  845.     { Returns the Absolute value of d                                 }
  846.     {*****************************************************************}
  847.     var
  848.      w: integer;
  849.     begin
  850.      w:=integer(d shr 16);
  851.      if w < 0 then
  852.      begin
  853.         w:=-w;                      { invert sign ...              }
  854.         d:=d and $ffff;
  855.         d:=d or (fixed(w) shl 16);  { add this to fixed number ... }
  856.         abs:=d;
  857.      end
  858.      else
  859.         abs:=d;                     { already positive... }
  860.     end;
  861.  
  862.  
  863.     function sqr(d : fixed) : fixed;
  864.     {*****************************************************************}
  865.     { Returns the Absolute squared value of d                         }
  866.     {*****************************************************************}
  867.     begin
  868.             {16-bit precision needed, not 32 =)}
  869.        sqr := d*d;
  870. {       sqr := (d SHR 8 * d) SHR 8; }
  871.     end;
  872.  
  873.  
  874.     function Round(x: fixed): longint;
  875.     {*****************************************************************}
  876.     { Returns the Rounded value of d as a longint                     }
  877.     {*****************************************************************}
  878.     var
  879.      lowf:integer;
  880.      highf:integer;
  881.     begin
  882.       lowf:=x and $ffff;       { keep decimal part ... }
  883.       highf :=integer(x shr 16);
  884.       if lowf > 5 then
  885.         highf:=highf+1
  886.       else
  887.       if lowf = 5 then
  888.       begin
  889.         { here we must check the sign ...       }
  890.         { if greater or equal to zero, then     }
  891.         { greater value will be found by adding }
  892.         { one...                                }
  893.          if highf >= 0 then
  894.            Highf:=Highf+1;
  895.       end;
  896.       Round:= longint(highf);
  897.     end;
  898. {$endif fixed}
  899.  
  900.     function power(bas,expo : real) : real;
  901.      begin
  902.         power:=exp(ln(bas)*expo);
  903.      end;
  904.  
  905.    function power(bas,expo : longint) : longint;
  906.      begin
  907.         power:=round(exp(ln(bas)*expo));
  908.      end;
  909.  
  910. {
  911.   $Log: math.inc,v $
  912.   Revision 1.1.1.1  1998/03/25 11:18:44  root
  913.   * Restored version
  914.  
  915.   Revision 1.6  1998/02/20 20:41:54  carl
  916.     + fixed other problems...
  917.  
  918.   Revision 1.5  1998/01/26 12:01:37  michael
  919.   + Added log at the end
  920.  
  921.  
  922.  
  923.   Working file: rtl/m68k/math.inc
  924.   description:
  925.   ----------------------------
  926.   revision 1.4
  927.   date: 1998/01/05 00:34:21;  author: carl;  state: Exp;  lines: +896 -903
  928.   * Licencing problem fixed.
  929.   ----------------------------
  930.   revision 1.3
  931.   date: 1997/12/01 12:37:22;  author: michael;  state: Exp;  lines: +14 -0
  932.   + added copyright reference in header.
  933.   ----------------------------
  934.   revision 1.2
  935.   date: 1997/11/28 16:51:54;  author: carl;  state: Exp;  lines: +901 -891
  936.   + added power.
  937.   ----------------------------
  938.   revision 1.1
  939.   date: 1997/11/27 13:57:50;  author: carl;  state: Exp;
  940.   m68k implementation of math routines. (Initial version)
  941.   =============================================================================
  942. }
  943.